package org.micro_gzm.v5.core;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import org.micro_gzm.v5.loaders.fbx.FBXLoader;

import android.content.res.AssetManager;
import android.util.Log;


public class GZM3DModel {
	
	private float[] vertices;
	private float[] normals;
	private float[] UVS;
	private short[] indices;
	
	private FloatBuffer vertexBuffer;
	private FloatBuffer normalBuffer;
	private FloatBuffer textCoordsBuffer;
	private ShortBuffer indexBuffer;
	
	private int numVertices;
	private int numNormals;
	private int numUVS;
	private int numIndices;
	
	private GZMMaterial material;
	
	static final int COORDS_PER_VERTEX = 3;
	
	public GZM3DModel() {
	}
	
	public void loadFBXFile(String filePath, AssetManager assets) {
		
		FBXLoader loader = new FBXLoader();
		
		try {
			
			loader.loadFBX(new BufferedReader(new InputStreamReader(assets.open(filePath), "UTF8")));
		}
		catch (IOException e) {
			
			Log.d("MG", "ResourceManager Error: " + e.getMessage());

			return;
		}
		
		GZMGeometry modelData = loader.getGeometryData();
		
		vertices = modelData.getFloatVerticesArray();
		normals = modelData.getFloatNormalsArray();
		UVS = modelData.getFloatUVSArray();
		indices = modelData.getShortIndicesArray();
		
		numVertices = vertices.length;
		numNormals = normals.length;
		numUVS = UVS.length;
		numIndices = indices.length;
		
		init();
	}
	
	public void setCube(float sizeIn) {
		
        vertices = new float[]{ -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f,
		                         -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
		                         0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f,
		                         -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f,
		                         -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
		                         0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f,
		                         -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
		                         0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, };

        normals = new float[]{ 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
	                         -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
	                         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
	                         0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
	                         0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
	                         1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
	                         -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
	                         0.0f, 0.0f, 1.0f, 0.0f, 0.0f, };

        UVS = new float[]{ 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                        1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                        0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                        1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
                        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, };
        
        indices = new short[]{ 0, 2, 1, 0, 3, 2, 4, 5, 6, 4, 6, 7, 8, 9, 10,
			                 8, 10, 11, 12, 15, 14, 12, 14, 13, 16, 17, 18, 16, 18, 19, 20,
			                 23, 22, 20, 22, 21, };
		
		numVertices = vertices.length;
		numNormals = normals.length;
		numUVS = UVS.length;
		numIndices = indices.length;
		
		init();
	}
	
	/**
	 * 
	 * @param dataIn - Mesh data (vertices, indices, etc)
	 */
	private void init() {

         // Allocate memory for buffers
         vertexBuffer = ByteBuffer.allocateDirect(numVertices * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
         normalBuffer = ByteBuffer.allocateDirect(numNormals * 3 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
         textCoordsBuffer = ByteBuffer.allocateDirect(numUVS * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
         indexBuffer = ByteBuffer.allocateDirect(numIndices * 2).order(ByteOrder.nativeOrder()).asShortBuffer();

         vertexBuffer.put(vertices).position(0);
         normalBuffer.put(normals).position(0);
         textCoordsBuffer.put(UVS).position(0);
         indexBuffer.put(indices).position(0);
	}
	
	/**
	 * GETTERS / SETTERS
	 */
    public FloatBuffer getVertices() {
            return vertexBuffer;
    }

    public FloatBuffer getNormals() {
            return normalBuffer;
    }

    public FloatBuffer getTexCoords() {
            return textCoordsBuffer;
    }

    public ShortBuffer getIndices() {
            return indexBuffer;
    }

    public int getNumIndices() {
            return numIndices;
    }
}
